Lena Vogl
  • Home
  • R & Excel
  • Karten mit R leaflet
  • Observable JS
  • Impressum

Inhalt

  • Einfache Karte
  • Karte mit Suchfunktion
  • Marker einfügen
  • Cluster
  • Individuelle Icons
  • Minicharts

R Leaflet

Leaflet ist eine Open Source Bibliothek mit der interaktive Karten erstellt werden können. Über das R-Package leaflet lassen sich verschiedene GIS-Daten (z.B. Koordinaten, Layer) in interaktiven Karten darstellen.

Einfache Karte

Um eine einfache LeafletKarte zu erstellen, benötigen wir eine Hintergrundkarte und einen Kartenausschnitt, der dargestellt werden soll. Die Region kann entweder über eine Koordinate herangezoomt werden, oder durch hinzufügen eines Layers (z.B. aus einer Shape-Datei). Es gibt eine Vielzahl an möglichen Hintergrunddaten. Eine sehr umfangreiche Übersicht an Hintergrundkarten findet man z.B. hier: Kartenauswahl

library(leaflet)
library(tidyverse)

leaflet() %>%
  # Mitte auf München setzen
  setView(lng = 11.572347, lat = 48.138345, zoom = 12) %>%
  # Hintergrundkarte festlegen
  addProviderTiles(providers$OpenStreetMap.DE, group = "Open Street Map DE") %>%
  # Zusätzliche Hintergrundkarten als Alternative
  addProviderTiles(providers$Esri.WorldImagery, group = "ESRI World Imagery") %>%
  # Auswahlfeld für den Nutzer um sich für eine Hintergrundkarte zu entscheiden
    addLayersControl(
     baseGroups = c("Open Street Map DE","ESRI World Imagery")     )

Karte mit Suchfunktion

Um Adressen suchen zu können, lässt sich mit dem package leaflet.extras ein Suchfenster einbinden (addSearchOSM()). Mit addReverseSearchOSM() lässt sich per Mouseklick die Adresse der angeklickten Stelle anzeigen. Mit addResetMapButton() wird ein Button integriert, mit dem man wieder in den ursprünglichen Kartenausschnitt zurückspringen kann.

library(leaflet.extras)

leaflet() %>%
  # Mitte auf München setzen
  setView(lng = 11.572347, lat = 48.138345, zoom = 12) %>%
  # Hintergrundkarte festlegen
  addProviderTiles(providers$OpenStreetMap.DE, group = "Open Street Map DE") %>%
  addSearchOSM() %>% 
  addReverseSearchOSM(showBounds = T, showSearchLocation = F) %>% 
  addResetMapButton()

Marker einfügen

Um Marker einzeichnet zu können, simulieren wir für Deutschland, Österreich und die Schweiz Koordinaten. Diese werden drei Kategorien zugeordnet, nach denen sie später eingefärbt werden können. Im Package rnaturalearth sind die Geometrien der Länder verfügbar.

library(rnaturalearth)
library(sf)

deu = ne_countries(country = "Germany", scale = "medium", returnclass = "sf") %>%
  # Transformation nach WGS84 (entspricht crs 4326)
  st_transform(crs = 4326)
oe = ne_countries(country = "Austria", scale = "medium", returnclass = "sf") %>%
  # Transformation nach WGS84 (entspricht crs 4326)
  st_transform(crs = 4326)
ch = ne_countries(country = "Switzerland", scale = "medium", returnclass = "sf") %>%
  # Transformation nach WGS84 (entspricht crs 4326)
  st_transform(crs = 4326)


#Koordinaten simulieren
set.seed(1234)
deutschand_punkte = st_sample(deu, size = 150)
oesterreich_punkte = st_sample(oe, size = 50)
schweiz_punkte = st_sample(ch, size = 50)

# Zu einem Datensatz zusammenfassen
#Deutschland
deutschand_punkte_df <- as.data.frame(st_coordinates(deutschand_punkte))
deutschand_punkte_df <- cbind(deutschand_punkte_df, Typ = sample(c("A", "B", "C"), size = nrow(deutschand_punkte_df), replace = T, prob = c(0.2, 0.3, 0.5))) %>%
  mutate(Land = "Deutschland")

# Österreich
oesterreich_punkte_df <- as.data.frame(st_coordinates(oesterreich_punkte))
oesterreich_punkte_df <- cbind(oesterreich_punkte_df, Typ = sample(c("A", "B", "C"), size = nrow(oesterreich_punkte_df), replace = T, prob = c(0.4, 0.1, 0.5))) %>%
  mutate(Land = "Österreich")

# Schweiz
schweiz_punkte_df <- as.data.frame(st_coordinates(schweiz_punkte))
schweiz_punkte_df <- cbind(schweiz_punkte_df, Typ = sample(c("A", "B", "C"), size = nrow(schweiz_punkte_df), replace = T, prob = c(0.6, 0.2, 0.2))) %>%
  mutate(Land = "Schweiz")

dach_df <- rbind(deutschand_punkte_df, oesterreich_punkte_df, schweiz_punkte_df)

Im Dataframe dach_df sind nun für die Länder Deutschand, Österreich und Schweiz die Koordinaten vorhanden.

 leaflet(data = dach_df) %>%
     addTiles() %>%  # Default ist hier OpenStreetMap
     addMarkers(~X, ~Y, popup = ~as.character(Typ), label = ~as.character(Typ))

Cluster

Besonders wenn es sich um viele Marker bei niedriger Zoomstufe handelt, ist die Darstellung der einzelnen Icons manchmal unübersichtlich. Teilweise gibt es auch Darstellungsprobleme wenn mehrere Marker mit der gleichen Koordinate hinterlegt sind. In solchen Fällen bietet sich eine Clusterdarstellung an.

leaflet(data = dach_df) %>%
     addTiles() %>%  
     addMarkers(~X, 
                ~Y, 
                popup = ~as.character(Typ), 
                label = ~as.character(Typ), 
                clusterOptions = markerClusterOptions())

Individuelle Icons

Sollen die drei verschiedenen Typen klarer voneinander unterscheidbar sein, so kann das über individuell gestaltete Icons erfolgen. Mit AwesomeIcons steht eine Vielzahl an Icons zur Verfügung. Eine Übersicht der Icons findet sich hier: fontawesome.

Wir nehmen an dass es sich bei den Typen A - C um verschiedenen Fahrzeugtypen handelt. Mögliche Icons könnten also so gestaltet werden:

# Icons für die verschiedenen Typen definieren
IconSet <- awesomeIconList(
  "A" = makeAwesomeIcon(icon = 'car', markerColor = 'blue', iconColor = 'black', library = "fa"),
  "B" = makeAwesomeIcon(icon = 'truck', markerColor = 'orange', iconColor = 'black', library = "fa"),
  "C" = makeAwesomeIcon(icon = 'motorcycle', markerColor = 'green', iconColor = 'black', library = "fa")
)

# Punktlayer erstellen
dach_df_punktlayer <- sp::SpatialPointsDataFrame(as.matrix(dach_df[,c("X","Y")]), dach_df[,c("Typ","Land")])

# Karte erstellen
leaflet(data = dach_df_punktlayer) %>%
     addTiles() %>%  
     addAwesomeMarkers(icon = ~IconSet[Typ], label = ~paste("Fahrzeugtyp ",as.character(Typ))) 

Minicharts

mit dem Package leaflet.minicharts lassen sich Verteilungen auf die Landkarte plotten. Dazu benötigen wir geeignete Daten zu den Ländern. In diesem Fall wird die Anzahl der Typen A - C je Land gezäht.

# Daten aus Koordinaten aggregieren:
dach_df_agg <- dach_df %>%
  group_by(Typ,Land) %>%
  summarize(Anz = n_distinct(X)) %>%
  pivot_wider(names_from = Typ,values_from = Anz) %>%
  ungroup()

dach_agg_ges = dach_df %>%
  group_by(Land) %>%
  summarize(X = mean(X), Y = mean(Y)) %>%
  ungroup() %>%
  left_join(dach_df_agg, by = "Land")

Diese Daten lassen sich nun als Balkendiagramme auf die einzelnen Länder legen.

library(leaflet.minicharts)

 leaflet(data = dach_agg_ges) %>%
     addProviderTiles(providers$Esri.WorldGrayCanvas) %>%  # Default ist hier OpenStreetMap
     addMinicharts(lng = dach_agg_ges$X, lat = dach_agg_ges$Y, type = "bar", chartdata = dach_agg_ges[,4:6], width =80, height = 80)